home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 011 / dfix.arc / DFIX.C < prev    next >
Encoding:
C/C++ Source or Header  |  1985-03-15  |  8.3 KB  |  256 lines

  1.  
  2. /*
  3. **            DFIX (C)1985 Howard Rumsey Jr.
  4. **
  5. **    DFIX disk fix utility. Reads the whole DOS partion on a disk (floppy,
  6. **    hard disk, ramdisk) and, if directed, marks bad clusters in the FAT(s).
  7. **
  8. **    Usage:
  9. **            dfix [d:]
  10. **
  11. **        d: is an optional device specifier. If not specified DFIX will
  12. **            use the default device.
  13. **
  14. **    If DFIX finds a bad cluster already allocated to a file this will
  15. **    be reported and no further action taken.  If DFIX finds an unallocated
  16. **    cluster it marks it's local copy of the FAT. At the end of the testing
  17. **    the user is asked if he wishes to permanently mark the cluster as BAD.
  18. **    
  19. */
  20.  
  21. /*
  22. **
  23. **    DFIX is a substitute for the disktest program included with Version 3
  24. **    of The Norton Utilities (tm?). The Norton package contains many other
  25. **    useful tools. I wrote this program and am placing it in public domain
  26. **    because of it's (sometimes) critical value.
  27. **
  28. **    This program may be freely copied and used for any non-commercial
  29. **    purpose.
  30. **
  31. **                Howard Rumsey
  32. **                Caltech
  33. **                Pasadena, CA 91125
  34. **
  35. **                CompuServe [72426,3722]
  36. **                March 1,1985
  37. **
  38. */
  39.  
  40. #include <stdio.h>
  41.  
  42. #define TRUE 1
  43. #define FALSE 0
  44.  
  45. #define DOS12 4086        /* FAT 12 or 16 bit MAGIC NUMBER */
  46. #define BADMARK 0xfff7        /* FAT entry for BAD cluster */
  47.  
  48. char *malloc();
  49.  
  50. main(ac,av) char *av[]; {
  51.     int dev;
  52.  
  53.     printf("DFIX (C) 1985 Howard Rumsey Jr.\n\n");
  54.     if((dosVersion() & 0xff) < 2) errexit("Must have DOS 2.0 or higher.\n");
  55.     if(ac == 1) {
  56.         show_usage();
  57.         dev = defaultdev(); }
  58.     else {
  59.         if(av[1][1] != ':' || !isalpha(av[1][0])) { show_usage(); exit(1); }
  60.         dev = toupper(av[1][0])-'A'; }
  61.     doOpen(dev);
  62.     doDisk(dev);
  63.     return 0; }
  64.  
  65. show_usage() {
  66.     fprintf(stderr, "DFIX will test the whole DOS partition.\n");
  67.     fprintf(stderr, "If you wish, it will mark bad sectors in the FAT.\n");
  68.     fprintf(stderr, "Usage:\n");
  69.     fprintf(stderr, "  dfix [d:]\n");
  70.     fprintf(stderr, "where d: is a device specifier.\n"); }
  71.  
  72. errexit(str) char *str; {
  73.     fputs(str, stderr);
  74.     exit(-1); }
  75.  
  76. char *plural(n) int n; {
  77.     return n>1 ? (char *)&"s" : (char *)&""; }
  78.  
  79. typedef unsigned int uint;
  80.  
  81. #define BSIZE (14+2*8)    /* Should be the size of the following structure */
  82. struct bootsec {    /* BOOT sector structure */
  83.     char jump[3];        /* jump around this stuff */
  84.     char oem[8];        /* OEM name, version */
  85.     uint bytpsec;        /* bytes per sector */
  86.     char secpclu;        /* sectors per cluster */
  87.     uint fatsec;        /* no. reserved sectors = FAT start */
  88.     char nfats;        /* number of FATs */
  89.     uint ndir;        /* number of ROOT directory entries */
  90.     uint totsec;        /* number of sectors in this partition */
  91.     char meddes;        /* media descriptor byte */
  92.     uint fatcnt;        /* number of sectors in a single FAT */
  93.     uint secptrk;        /* sectors per track */
  94.     uint nheads;        /* number of heads this device */
  95.     uint hidsec;        /* number of hidden sectors */
  96. } *boot;
  97.  
  98. int fat12;        /* TRUE if 12 bit FAT entries */
  99. int rdsize;        /* ROOT directory size in sectors */
  100. char *fattab;        /* pointer to local copy of FAT */
  101. char *clubuf;        /* points to cluster input buffer */
  102.  
  103. extern struct {        /* communicate area for device allocation data */
  104.     int d;        /* device number A=0,... */
  105.     char mb;    /* media byte */
  106.     char spc;    /* sectors per cluster */
  107.     uint nc;    /* number clusters */
  108.     uint ss;    /* sector size */
  109. } _alloc_tab;
  110.  
  111. doOpen(dev) int dev; {
  112.     /* Check the size of bootsec to avoid a mismatch between
  113.         "C" and DOS data allocation */
  114.     if(sizeof(struct bootsec) != BSIZE) errexit("BOOT sector data problem. Sorry!\n");
  115.  
  116.     /* Gather and print the device parameters */
  117.  
  118.     _alloc_tab.d = dev;
  119.     devAlloc();        /* build the device allocation table */
  120.     boot = (struct bootsec *) malloc(_alloc_tab.ss);
  121.     if(boot == NULL) errexit("Can't allocate BOOT buffer\n");
  122.     if(rdDevice(dev, 0, 1, boot) != 0) errexit("Can't read BOOT sector\n");
  123.     /* test for compatibility of BOOT sector and _alloc_tab */
  124.     if(_alloc_tab.mb  != boot->meddes ||
  125.        _alloc_tab.spc != boot->secpclu ||
  126.        _alloc_tab.ss  != boot->bytpsec ) 
  127.         errexit("BOOT sector information error. Possibly non-DOS 2+ media.\n");
  128.  
  129.     /* do we have 12 bit FAT entries? */    
  130.     fat12 = (_alloc_tab.nc < DOS12);
  131.     /* compute ROOT directory size */
  132.     rdsize = (int) ((boot->ndir * 32L)/boot->bytpsec);
  133.  
  134.     /* print the device information */
  135.     printf("\nInformation for Device %c:\n",'A'+dev);
  136.     printf("  OEM name: %8s\n",boot->oem);
  137.     printf("  There are %d bytes per sector.\n",boot->bytpsec);
  138.     if(boot->secpclu == 1)
  139.       printf("  There is one sector per cluster.\n");
  140.     else
  141.       printf("  There are %d sectors per cluster.\n",boot->secpclu);
  142.     printf("  There are %d clusters numbered from 2.\n", _alloc_tab.nc);
  143.     if(boot->nfats == 1)
  144.       printf("  There is one FAT, %d sector%s long.\n", boot->fatcnt, plural(boot->fatcnt));
  145.     else
  146.       printf("  There are %d FATs, each %d sector%s long.\n", boot->nfats, boot->fatcnt, plural(boot->fatcnt));
  147.     printf("  The ROOT directory can hold %d entries and is %d sectors long.\n", boot->ndir, rdsize);
  148. }
  149.  
  150.  
  151. doDisk(dev) int dev; {    /* read the FATs, ROOT-dir, and clusters */
  152.     int lsec;    /* logical sector number */
  153.     int jf, kf;
  154.     int nbad, newbad, nbadf;     /* counters for bad clusters */
  155.     char yesno[80];        /* answer 'update' question */
  156.     
  157.     /* get space for one FAT and one cluster */
  158.     fattab = malloc(boot->fatcnt * boot->bytpsec);
  159.     if(fattab == NULL)
  160.       errexit("Unable to allocate memory for a FAT.\n");
  161.     clubuf = malloc(boot->bytpsec * boot->secpclu);
  162.     if(clubuf == NULL)
  163.       errexit("Unable to allocate memory for reading clusters.\n");
  164.  
  165.     printf("Reading the first FAT.\n");
  166.     if(rdDevice(dev, boot->fatsec, boot->fatcnt, fattab) != 0)
  167.       errexit("Can't read first FAT. Device unusable.\n");
  168.  
  169.     /* read the rest, one sector at a time */
  170.     lsec = boot->fatsec + boot->fatcnt;
  171.     for(jf=1; jf<boot->nfats; jf++) {
  172.     printf("Reading the next FAT.\n");
  173.         for(kf=0; kf<boot->fatcnt; kf++) {
  174.             if(rdDevice(dev, lsec++, 1, clubuf) != 0)
  175.               errexit("Error reading second (or later) FAT.\n");
  176.             /* should compair FATs */ } }
  177.  
  178.     printf("Reading the ROOT directory.\n");
  179.     for(jf=0; jf<rdsize; jf++)
  180.       if(rdDevice(dev, lsec++, 1, clubuf) != 0)
  181.         errexit("Error reading the ROOT directory. Device unusable.\n");
  182.  
  183.     nbad = newbad = nbadf = 0;
  184.     printf("Checking the clusters now.\n");
  185.     printf("Cluster      ");
  186.     for(jf=2; jf<_alloc_tab.nc+2; jf++) {
  187.         printf("\b\b\b\b\b%5d",jf);
  188.         if(rdDevice(dev, lsec, boot->secpclu, clubuf) != 0) {
  189.             nbad++;
  190.             printf("\007 is bad. ");
  191.             switch(fatstat(jf)) {
  192.  
  193.                 case 0:
  194.                 newbad++;
  195.                 printf("Unallocated.\n");
  196.                 pokefat(jf,BADMARK);
  197.                 break;
  198.  
  199.                 case BADMARK:
  200.                 printf("Already marked as bad.\n");
  201.                 break;
  202.  
  203.                 default:
  204.                 nbadf++;
  205.                 printf("Included in some file. Not marked.\n");
  206.                 break; }
  207.             printf("Cluster      "); }
  208.         lsec += boot->secpclu; }
  209.     printf("\b\b\b\b\b\b\b\b\b\b\b\b\b");
  210.     if(nbad == 0) {
  211.         printf("No bad clusters were found.\n");
  212.         return; }
  213.     printf("The number of bad clusters found was %d.\n",nbad);
  214.     if(nbadf != 0) {
  215.         if(nbad == 1) printf("Some file has a bad cluster.\n");
  216.         else printf("One or more files have bad clusters.");
  217.         printf("The DOS command:\n  copy *.* nul\n");
  218.         printf("will check all the files in the default directory.\n");
  219.         printf("Use the DOS 'RECOVER' utility to repair bad files.\n");
  220.         printf("Then erase the bad files and run DFIX again.\n"); }
  221.     if(newbad == 0) {
  222.         printf("No %s bad clusters were found.", nbadf ? "repairable" : "new");
  223.         return; }
  224.     printf("The number of repairable bad clusters is %d.\n", newbad);
  225.     printf("Do you wish to update the FAT? (y/n) ");
  226.     gets(yesno);
  227.     if(toupper(*yesno) == 'Y') {
  228.         for(jf=0, lsec=boot->fatsec; jf<boot->nfats; jf++, lsec += boot->fatcnt)
  229.           if(wrDevice(dev, lsec, boot->fatcnt, fattab) != 0)
  230.             errexit("Can't write new FAT. Device maybe unusable\n");
  231.         printf("FAT updated.\n"); }
  232.     else printf("FAT not updated.\n");
  233. }
  234.  
  235. fatstat(c) unsigned c; {
  236.     int *jj;
  237.     if(fat12) {
  238.         jj = (int *) (fattab+((c+c+c) >> 4));
  239.         if(c&1) return((*jj >> 4) & 0xfff);
  240.         return *jj & 0xfff; }
  241.     return ((int *) fattab)[c];
  242. }
  243.  
  244. pokefat(c,bm) unsigned c, bm; {
  245.     int *jj;
  246.     if(fat12) {
  247.         jj = (int *) (fattab+((c+c+c) >> 4));
  248.         if(c&1) {
  249.             *jj = (*jj & 0xf) | (bm<<4);
  250.             return; }
  251.         *jj = (*jj & 0xf000) | (bm & 0xfff);
  252.         return; }
  253.     ((int *) fattab)[c] = (int) bm;
  254. }
  255.  
  256.